using Microsoft.Extensions.Logging;
using SeataNet.Core.Configuration;
using SeataNet.Core.Exceptions;
using SeataNet.Core.Protocol;

namespace SeataNet.Core.RPC
{
    /// <summary>
    /// RPC客户端连接管理器接口
    ///
    /// 定义RPC客户端连接的生命周期管理。
    /// 负责建立、维护和断开与Seata服务器的连接。
    /// </summary>
    public interface IConnectionManager
    {
        /// <summary>
        /// 异步建立连接
        ///
        /// 与服务器建立连接，通常通过发送心跳检测来验证连接有效性。
        /// </summary>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns>连接是否成功</returns>
        Task<bool> ConnectAsync(CancellationToken cancellationToken = default);

        /// <summary>
        /// 异步断开连接
        ///
        /// 关闭与服务器的连接，释放资源。
        /// </summary>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns>断开连接的异步任务</returns>
        Task DisconnectAsync(CancellationToken cancellationToken = default);

        /// <summary>
        /// 获取当前连接状态
        /// </summary>
        bool IsConnected { get; }

        /// <summary>
        /// 连接状态改变事件
        ///
        /// 当连接状态发生变化时触发此事件。
        /// 事件的值为true表示连接已建立，false表示连接已断开。
        /// </summary>
        event EventHandler<bool> ConnectionStateChanged;
    }

    /// <summary>
    /// 默认RPC客户端连接管理器实现
    ///
    /// 职责：
    /// 1. 管理与Seata TC服务器的连接生命周期
    /// 2. 定期发送心跳包保活连接
    /// 3. 检测并处理连接异常
    /// 4. 在连接状态变化时通知监听器
    ///
    /// 心跳机制：
    /// - 按照配置的间隔定期发送心跳请求
    /// - 如果心跳失败，标记连接为断开状态
    /// - 外部可以手动触发连接检查
    ///
    /// 线程安全：
    /// - 使用volatile关键字和lock保护连接状态
    /// - 支持并发的连接状态读取
    /// </summary>
    public class DefaultConnectionManager : IConnectionManager, IDisposable
    {
        private readonly HttpClient _httpClient;
        private readonly SeataConfiguration _configuration;
        private readonly ILogger<DefaultConnectionManager> _logger;
        private readonly ILoggerFactory _loggerFactory;
        // 定时器：每隔一段时间发送一次心跳
        private readonly Timer _heartbeatTimer;
        // 连接状态标志，使用volatile保证可见性
        private volatile bool _isConnected;
        // 并发访问锁
        private readonly object _lock = new object();

        public bool IsConnected => _isConnected;

        public event EventHandler<bool> ConnectionStateChanged;

        public DefaultConnectionManager(
            HttpClient httpClient,
            SeataConfiguration configuration,
            ILogger<DefaultConnectionManager> logger,
            ILoggerFactory loggerFactory)
        {
            _httpClient = httpClient;
            _configuration = configuration;
            _logger = logger;
            _loggerFactory = loggerFactory;
            
            // 初始化心跳定时器
            _heartbeatTimer = new Timer(
                async _ => await SendHeartbeatAsync(),
                null,
                TimeSpan.Zero,
                TimeSpan.FromMilliseconds(_configuration.Transport.HeartbeatInterval));
        }

        public async Task<bool> ConnectAsync(CancellationToken cancellationToken = default)
        {
            lock (_lock)
            {
                if (_isConnected)
                {
                    return true;
                }
            }

            try
            {
                _logger.LogInformation($"正在连接到Seata服务器: {_configuration.Transport.ServerAddress}");
                
                // 发送心跳测试连接
                var heartbeatRequest = new HeartbeatRequest();
                var heartbeatResponse = await SendHeartbeatRequestAsync(heartbeatRequest, cancellationToken);
                
                if (heartbeatResponse != null)
                {
                    lock (_lock)
                    {
                        _isConnected = true;
                    }
                    
                    _logger.LogInformation("成功连接到Seata服务器");
                    OnConnectionStateChanged(true);
                    return true;
                }
                
                return false;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"连接到Seata服务器失败: {_configuration.Transport.ServerAddress}");
                return false;
            }
        }

        public async Task DisconnectAsync(CancellationToken cancellationToken = default)
        {
            lock (_lock)
            {
                if (!_isConnected)
                {
                    return;
                }
            }

            try
            {
                _logger.LogInformation("正在断开与Seata服务器的连接");
                
                lock (_lock)
                {
                    _isConnected = false;
                }
                
                OnConnectionStateChanged(false);
                _logger.LogInformation("已断开与Seata服务器的连接");
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "断开连接时发生错误");
            }
        }

        private async Task SendHeartbeatAsync()
        {
            if (!_isConnected)
            {
                return;
            }

            try
            {
                var heartbeatRequest = new HeartbeatRequest();
                var heartbeatResponse = await SendHeartbeatRequestAsync(heartbeatRequest);
                
                if (heartbeatResponse == null)
                {
                    _logger.LogWarning("心跳失败，可能已断开连接");
                    lock (_lock)
                    {
                        _isConnected = false;
                    }
                    OnConnectionStateChanged(false);
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "发送心跳时发生错误");
                lock (_lock)
                {
                    _isConnected = false;
                }
                OnConnectionStateChanged(false);
            }
        }

        private async Task<HeartbeatResponse> SendHeartbeatRequestAsync(HeartbeatRequest request, CancellationToken cancellationToken = default)
        {
            try
            {
                var serializerLogger = _loggerFactory.CreateLogger<BinaryMessageSerializer>();
                var serializer = new BinaryMessageSerializer(serializerLogger);
                var content = new ByteArrayContent(serializer.Serialize(request));
                
                var response = await _httpClient.PostAsync(
                    $"{_configuration.Transport.ServerAddress}/seata/heartbeat",
                    content,
                    cancellationToken);
                
                if (response.IsSuccessStatusCode)
                {
                    var responseData = await response.Content.ReadAsByteArrayAsync(cancellationToken);
                    return (HeartbeatResponse)serializer.Deserialize(responseData);
                }
                
                return null;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "发送心跳请求时发生错误");
                return null;
            }
        }

        protected virtual void OnConnectionStateChanged(bool isConnected)
        {
            ConnectionStateChanged?.Invoke(this, isConnected);
        }

        public void Dispose()
        {
            _heartbeatTimer?.Dispose();
            _httpClient?.Dispose();
        }
    }

    /// <summary>
    /// RPC客户端负载均衡器接口
    ///
    /// 定义负载均衡算法的标准接口。
    /// 负责从可用服务器列表中选择一个目标服务器。
    /// </summary>
    public interface ILoadBalancer
    {
        /// <summary>
        /// 从服务器列表中选择一个目标服务器
        /// </summary>
        /// <param name="servers">可用服务器列表</param>
        /// <returns>被选中的服务器地址</returns>
        string SelectServer(IList<string> servers);
    }

    /// <summary>
    /// 轮询负载均衡器
    ///
    /// 职责：
    /// 按照顺序依次选择服务器，实现请求的均匀分配。
    ///
    /// 工作原理：
    /// 1. 维护一个当前索引(_currentIndex)
    /// 2. 每次选择时返回当前索引对应的服务器
    /// 3. 索引递增并对服务器数量取模，实现循环轮询
    /// 4. 使用锁保证线程安全
    ///
    /// 适用场景：
    /// - 各服务器性能相近
    /// - 希望请求均匀分配
    /// - 适合长连接场景
    ///
    /// 线程安全：
    /// 使用lock(_lock)保护索引的读取和更新操作。
    /// </summary>
    public class RoundRobinLoadBalancer : ILoadBalancer
    {
        // 当前索引，指向下一个要选择的服务器位置
        private int _currentIndex = 0;
        // 并发访问锁
        private readonly object _lock = new object();

        /// <summary>
        /// 选择下一个服务器（轮询方式）
        ///
        /// 流程：
        /// 1. 验证服务器列表不为空
        /// 2. 获取当前索引对应的服务器
        /// 3. 索引递增，并对服务器总数取模实现循环
        /// 4. 返回选中的服务器
        ///
        /// 示例：
        /// 服务器列表：[A, B, C]
        /// 第1次调用 -> A (index=0, next=1)
        /// 第2次调用 -> B (index=1, next=2)
        /// 第3次调用 -> C (index=2, next=0)
        /// 第4次调用 -> A (index=0, next=1) ...循环
        /// </summary>
        /// <param name="servers">可用服务器列表</param>
        /// <returns>选中的服务器地址</returns>
        /// <exception cref="ArgumentException">服务器列表为空时抛出</exception>
        public string SelectServer(IList<string> servers)
        {
            if (servers == null || servers.Count == 0)
            {
                throw new ArgumentException("服务器列表不能为空");
            }

            lock (_lock)
            {
                // 获取当前索引对应的服务器
                var server = servers[_currentIndex];
                // 索引递增并取模，实现循环
                _currentIndex = (_currentIndex + 1) % servers.Count;
                return server;
            }
        }
    }

    /// <summary>
    /// 随机负载均衡器
    ///
    /// 职责：
    /// 随机选择一个可用服务器，实现请求的随机分配。
    ///
    /// 工作原理：
    /// 1. 使用Random生成随机数
    /// 2. 随机数对服务器数量取模得到索引
    /// 3. 返回该索引对应的服务器
    ///
    /// 适用场景：
    /// - 各服务器性能相近
    /// - 不需要严格的均匀分配
    /// - 适合短连接场景
    /// - 简单快速
    ///
    /// 优点：
    /// - 实现简单
    /// - 无需维护状态
    /// - 在大量请求下趋于均匀分布
    ///
    /// 缺点：
    /// - 少量请求时可能分布不均
    /// - 无法保证严格的轮询
    /// </summary>
    public class RandomLoadBalancer : ILoadBalancer
    {
        // 随机数生成器
        private readonly Random _random = new Random();

        /// <summary>
        /// 随机选择一个服务器
        ///
        /// 流程：
        /// 1. 验证服务器列表不为空
        /// 2. 生成0到服务器数量-1之间的随机索引
        /// 3. 返回该索引对应的服务器
        ///
        /// 示例：
        /// 服务器列表：[A, B, C]
        /// 第1次调用 -> B (随机)
        /// 第2次调用 -> A (随机)
        /// 第3次调用 -> B (随机)
        /// 第4次调用 -> C (随机) ...完全随机
        /// </summary>
        /// <param name="servers">可用服务器列表</param>
        /// <returns>随机选中的服务器地址</returns>
        /// <exception cref="ArgumentException">服务器列表为空时抛出</exception>
        public string SelectServer(IList<string> servers)
        {
            if (servers == null || servers.Count == 0)
            {
                throw new ArgumentException("服务器列表不能为空");
            }

            // 生成随机索引并返回对应的服务器
            var index = _random.Next(servers.Count);
            return servers[index];
        }
    }

    /// <summary>
    /// RPC客户端重试策略接口
    ///
    /// 定义RPC调用失败时的重试逻辑。
    /// 决定是否需要重试以及重试前的等待时间。
    /// </summary>
    public interface IRetryPolicy
    {
        /// <summary>
        /// 判断是否应该重试
        /// </summary>
        /// <param name="attempt">当前重试次数（从1开始）</param>
        /// <param name="exception">导致失败的异常</param>
        /// <returns>true表示应该重试，false表示不再重试</returns>
        bool ShouldRetry(int attempt, Exception exception);

        /// <summary>
        /// 获取重试前的延迟时间
        /// </summary>
        /// <param name="attempt">当前重试次数（从1开始）</param>
        /// <returns>重试前需要等待的时间</returns>
        TimeSpan GetDelay(int attempt);
    }

    /// <summary>
    /// 固定间隔重试策略
    ///
    /// 职责：
    /// 每次重试之间使用固定的时间间隔。
    ///
    /// 工作原理：
    /// 1. 限制最大重试次数
    /// 2. 每次重试前等待固定的时间间隔
    /// 3. 超过最大次数后停止重试
    ///
    /// 适用场景：
    /// - 临时性网络抖动
    /// - 快速恢复的短暂故障
    /// - 不希望等待时间过长的场景
    ///
    /// 示例：
    /// maxAttempts=3, interval=1秒
    /// 第1次失败 -> 等待1秒 -> 第1次重试
    /// 第2次失败 -> 等待1秒 -> 第2次重试
    /// 第3次失败 -> 等待1秒 -> 第3次重试
    /// 第4次失败 -> 不再重试
    /// </summary>
    public class FixedIntervalRetryPolicy : IRetryPolicy
    {
        // 最大重试次数
        private readonly int _maxAttempts;
        // 每次重试的固定间隔
        private readonly TimeSpan _interval;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="maxAttempts">最大重试次数</param>
        /// <param name="interval">重试间隔时间</param>
        public FixedIntervalRetryPolicy(int maxAttempts, TimeSpan interval)
        {
            _maxAttempts = maxAttempts;
            _interval = interval;
        }

        /// <summary>
        /// 判断是否应该重试
        ///
        /// 只要当前重试次数小于最大次数就继续重试。
        /// </summary>
        /// <param name="attempt">当前重试次数</param>
        /// <param name="exception">导致失败的异常（此策略不关心异常类型）</param>
        /// <returns>是否应该重试</returns>
        public bool ShouldRetry(int attempt, Exception exception)
        {
            return attempt < _maxAttempts;
        }

        /// <summary>
        /// 获取重试延迟时间
        ///
        /// 始终返回固定的间隔时间，与重试次数无关。
        /// </summary>
        /// <param name="attempt">当前重试次数（此策略不使用该参数）</param>
        /// <returns>固定的重试间隔</returns>
        public TimeSpan GetDelay(int attempt)
        {
            return _interval;
        }
    }

    /// <summary>
    /// 指数退避重试策略
    ///
    /// 职责：
    /// 每次重试之间的等待时间呈指数增长。
    ///
    /// 工作原理：
    /// 1. 第1次重试等待 initialDelay
    /// 2. 第2次重试等待 initialDelay * backoffMultiplier
    /// 3. 第3次重试等待 initialDelay * backoffMultiplier²
    /// 4. 以此类推，直到达到maxDelay上限
    ///
    /// 适用场景：
    /// - 服务器过载或繁忙
    /// - 需要给服务器恢复时间
    /// - 避免对故障服务器造成额外压力
    /// - 网络拥塞场景
    ///
    /// 优点：
    /// - 避免雪崩效应（多个客户端同时重试）
    /// - 给服务器足够的恢复时间
    /// - 适应不同严重程度的故障
    ///
    /// 示例：
    /// maxAttempts=5, initialDelay=100ms, maxDelay=10s, multiplier=2.0
    /// 第1次失败 -> 等待100ms -> 第1次重试
    /// 第2次失败 -> 等待200ms -> 第2次重试
    /// 第3次失败 -> 等待400ms -> 第3次重试
    /// 第4次失败 -> 等待800ms -> 第4次重试
    /// 第5次失败 -> 等待1600ms -> 第5次重试
    /// 第6次失败 -> 不再重试
    /// </summary>
    public class ExponentialBackoffRetryPolicy : IRetryPolicy
    {
        // 最大重试次数
        private readonly int _maxAttempts;
        // 初始延迟时间
        private readonly TimeSpan _initialDelay;
        // 最大延迟时间（防止等待时间过长）
        private readonly TimeSpan _maxDelay;
        // 退避倍数（默认为2.0，即每次翻倍）
        private readonly double _backoffMultiplier;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="maxAttempts">最大重试次数</param>
        /// <param name="initialDelay">初始延迟时间</param>
        /// <param name="maxDelay">最大延迟时间上限</param>
        /// <param name="backoffMultiplier">退避倍数，默认为2.0（每次翻倍）</param>
        public ExponentialBackoffRetryPolicy(
            int maxAttempts,
            TimeSpan initialDelay,
            TimeSpan maxDelay,
            double backoffMultiplier = 2.0)
        {
            _maxAttempts = maxAttempts;
            _initialDelay = initialDelay;
            _maxDelay = maxDelay;
            _backoffMultiplier = backoffMultiplier;
        }

        /// <summary>
        /// 判断是否应该重试
        ///
        /// 只要当前重试次数小于最大次数就继续重试。
        /// </summary>
        /// <param name="attempt">当前重试次数</param>
        /// <param name="exception">导致失败的异常（此策略不关心异常类型）</param>
        /// <returns>是否应该重试</returns>
        public bool ShouldRetry(int attempt, Exception exception)
        {
            return attempt < _maxAttempts;
        }

        /// <summary>
        /// 获取指数增长的重试延迟时间
        ///
        /// 计算公式：delay = initialDelay * (backoffMultiplier ^ (attempt - 1))
        /// 如果计算结果超过maxDelay，则返回maxDelay。
        ///
        /// 示例（initialDelay=100ms, multiplier=2.0）：
        /// attempt=1 -> 100ms * 2^0 = 100ms
        /// attempt=2 -> 100ms * 2^1 = 200ms
        /// attempt=3 -> 100ms * 2^2 = 400ms
        /// attempt=4 -> 100ms * 2^3 = 800ms
        /// attempt=5 -> 100ms * 2^4 = 1600ms
        /// </summary>
        /// <param name="attempt">当前重试次数（从1开始）</param>
        /// <returns>本次重试的延迟时间</returns>
        public TimeSpan GetDelay(int attempt)
        {
            // 计算指数增长的延迟时间
            var delay = TimeSpan.FromMilliseconds(_initialDelay.TotalMilliseconds * Math.Pow(_backoffMultiplier, attempt - 1));
            // 限制最大延迟时间
            return delay > _maxDelay ? _maxDelay : delay;
        }
    }

    /// <summary>
    /// RPC客户端熔断器接口
    ///
    /// 定义熔断器的标准接口。
    /// 当服务持续失败时自动熔断，避免雪崩效应。
    /// </summary>
    public interface ICircuitBreaker
    {
        /// <summary>
        /// 执行操作（带熔断保护）
        ///
        /// 如果熔断器处于打开状态，直接拒绝执行并抛出异常。
        /// 如果熔断器处于关闭或半开状态，执行操作并根据结果更新熔断器状态。
        /// </summary>
        /// <typeparam name="T">操作返回值类型</typeparam>
        /// <param name="action">待执行的异步操作</param>
        /// <returns>操作的返回值</returns>
        /// <exception cref="CircuitBreakerOpenException">熔断器打开时抛出</exception>
        Task<T> ExecuteAsync<T>(Func<Task<T>> action);

        /// <summary>
        /// 获取熔断器是否处于打开状态
        /// </summary>
        bool IsOpen { get; }

        /// <summary>
        /// 重置熔断器到关闭状态
        ///
        /// 清除失败计数，允许请求通过。
        /// </summary>
        void Reset();
    }

    /// <summary>
    /// 默认RPC客户端熔断器实现
    ///
    /// 职责：
    /// 防止系统持续调用失败的服务，避免资源浪费和雪崩效应。
    ///
    /// 工作原理 - 三状态机：
    /// 1. **关闭状态(Closed)**：正常状态，允许所有请求通过
    ///    - 记录失败次数
    ///    - 当失败次数达到阈值时 -> 转为打开状态
    ///
    /// 2. **打开状态(Open)**：熔断状态，拒绝所有请求
    ///    - 直接抛出CircuitBreakerOpenException
    ///    - 经过恢复超时时间后 -> 转为半开状态
    ///
    /// 3. **半开状态(HalfOpen)**：试探状态，允许部分请求通过
    ///    - 如果请求成功 -> 转为关闭状态，清除失败计数
    ///    - 如果请求失败 -> 转为打开状态，重新计时
    ///
    /// 适用场景：
    /// - 防止级联故障
    /// - 快速失败，避免长时间等待
    /// - 给故障服务恢复时间
    ///
    /// 线程安全：
    /// 使用lock(_lock)保护状态变更和计数器操作。
    ///
    /// 示例场景：
    /// 1. 初始状态：Closed，正常处理请求
    /// 2. 连续5次失败（达到阈值）-> Open
    /// 3. Open状态持续30秒 -> HalfOpen
    /// 4. HalfOpen状态下请求成功 -> Closed
    /// 5. 如果HalfOpen状态下请求失败 -> Open（重新开始30秒计时）
    /// </summary>
    public class DefaultCircuitBreaker : ICircuitBreaker
    {
        // 失败阈值：连续失败多少次后打开熔断器
        private readonly int _failureThreshold;
        // 恢复超时：熔断器打开后多久尝试半开
        private readonly TimeSpan _recoveryTimeout;
        // 并发访问锁
        private readonly object _lock = new object();
        // 失败计数器
        private int _failureCount;
        // 最后一次失败的时间
        private DateTime _lastFailureTime;
        // 熔断器当前状态
        private CircuitBreakerState _state = CircuitBreakerState.Closed;

        /// <summary>
        /// 获取熔断器是否处于打开状态
        /// </summary>
        public bool IsOpen => _state == CircuitBreakerState.Open;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="failureThreshold">失败阈值，达到此值后打开熔断器</param>
        /// <param name="recoveryTimeout">恢复超时时间，打开后等待此时间进入半开状态</param>
        public DefaultCircuitBreaker(int failureThreshold, TimeSpan recoveryTimeout)
        {
            _failureThreshold = failureThreshold;
            _recoveryTimeout = recoveryTimeout;
        }

        /// <summary>
        /// 执行操作（带熔断保护）
        ///
        /// 流程：
        /// 1. 检查熔断器状态
        ///    - Open -> 检查是否超过恢复时间
        ///      - 是 -> 进入HalfOpen状态
        ///      - 否 -> 抛出CircuitBreakerOpenException
        /// 2. 执行操作
        /// 3. 操作成功 -> 如果是HalfOpen状态，转为Closed并清除失败计数
        /// 4. 操作失败 -> 增加失败计数，可能触发状态转换
        /// </summary>
        /// <typeparam name="T">操作返回值类型</typeparam>
        /// <param name="action">待执行的操作</param>
        /// <returns>操作的返回值</returns>
        /// <exception cref="CircuitBreakerOpenException">熔断器打开时抛出</exception>
        public async Task<T> ExecuteAsync<T>(Func<Task<T>> action)
        {
            // 第一步：检查熔断器状态
            lock (_lock)
            {
                if (_state == CircuitBreakerState.Open)
                {
                    // 检查是否达到恢复时间
                    if (DateTime.UtcNow - _lastFailureTime > _recoveryTimeout)
                    {
                        // 进入半开状态，允许试探性请求
                        _state = CircuitBreakerState.HalfOpen;
                    }
                    else
                    {
                        // 仍在熔断期，拒绝请求
                        throw new CircuitBreakerOpenException("熔断器已打开，拒绝执行请求");
                    }
                }
            }

            // 第二步：执行操作
            try
            {
                var result = await action();

                // 第三步：操作成功，更新状态
                lock (_lock)
                {
                    if (_state == CircuitBreakerState.HalfOpen)
                    {
                        // 半开状态下成功 -> 关闭熔断器，重置失败计数
                        _state = CircuitBreakerState.Closed;
                        _failureCount = 0;
                    }
                }

                return result;
            }
            catch (Exception ex)
            {
                // 第四步：操作失败，更新失败计数和状态
                lock (_lock)
                {
                    _failureCount++;
                    _lastFailureTime = DateTime.UtcNow;

                    // 失败次数达到阈值 -> 打开熔断器
                    if (_failureCount >= _failureThreshold)
                    {
                        _state = CircuitBreakerState.Open;
                    }
                }

                throw;
            }
        }

        /// <summary>
        /// 重置熔断器
        ///
        /// 强制将熔断器重置为关闭状态，清除所有失败记录。
        /// 适用于手动干预或服务恢复后的重置操作。
        /// </summary>
        public void Reset()
        {
            lock (_lock)
            {
                _state = CircuitBreakerState.Closed;
                _failureCount = 0;
            }
        }

        /// <summary>
        /// 熔断器状态枚举
        /// </summary>
        private enum CircuitBreakerState
        {
            /// <summary>
            /// 关闭状态：正常工作，允许所有请求通过
            /// </summary>
            Closed,

            /// <summary>
            /// 打开状态：熔断中，拒绝所有请求
            /// </summary>
            Open,

            /// <summary>
            /// 半开状态：试探状态，允许少量请求通过以测试服务是否恢复
            /// </summary>
            HalfOpen
        }
    }

    /// <summary>
    /// 熔断器打开异常
    ///
    /// 当熔断器处于打开状态时，拒绝执行请求并抛出此异常。
    /// 告知调用方当前服务不可用，避免无谓的等待和资源消耗。
    /// </summary>
    public class CircuitBreakerOpenException : RpcException
    {
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="message">异常消息</param>
        public CircuitBreakerOpenException(string message) : base(message)
        {
        }

        /// <summary>
        /// 构造函数（带内部异常）
        /// </summary>
        /// <param name="message">异常消息</param>
        /// <param name="innerException">内部异常</param>
        public CircuitBreakerOpenException(string message, Exception innerException) : base(message, innerException)
        {
        }
    }
}